package com.ncf.jucai.accessmeter;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 首页 handler Created by lichengwen on 7/11/16.
 */
class MeterRenderer extends AbstractHandler
{
    @Override
    public void handle(
            String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException
    {
        // 根据消耗时间统计
        // key的定义如下： 0：表示100毫秒以内 100：表示100-300毫秒 300：表示300-500毫秒 500：表示500-1000毫秒 1000：表示一秒以上
        int[][] costRanges = new int[][] {{0, 100}, {100, 300}, {300, 500}, {500, 1000}, {1000}};
        Map<String, Counter> costRangeMap = new LinkedHashMap<>();
        for (int[] range : costRanges) {
            costRangeMap.put(makeRangeKey(range), new Counter());
        }
        double totalCount = 0;
        for (Map.Entry<Integer, Counter> e : AccessLogAnalyzer.costCounters.entrySet()) {
            totalCount += e.getValue().getCount();
            for (int[] range : costRanges) {
                if ((range.length == 1 && e.getKey() >= range[0]) ||
                    (range.length == 2 && range[1] > e.getKey() && e.getKey() >= range[0])) {
                    costRangeMap.get(makeRangeKey(range)).plus(e.getValue().getCount());
                }
            }
        }

        // 统计1/10个访问日志的平均值
        Map<String, Double> countRangeMap = new LinkedHashMap<>();
        int countStep = (int) (totalCount / 10);
        Iterator<Map.Entry<Integer, Counter>> itr = AccessLogAnalyzer.costCounters.entrySet().iterator();
        int countAccumulation = 0;
        double costAccumulation = 0;
        for (int i = 0; i < 10; i++) {
            String key = i + "0% - " + (i + 1) + "0%";
            if (countAccumulation >= countStep) {
                countRangeMap.put(key, costAccumulation / countAccumulation);
                costAccumulation = costAccumulation / countAccumulation * (countAccumulation - countStep);
                countAccumulation -= countStep;
            } else {
                while (itr.hasNext()) {
                    Map.Entry<Integer, Counter> cur = itr.next();
                    if (countAccumulation + cur.getValue().getCount() >= countStep) {
                        int countBeyondThisStep = countAccumulation + cur.getValue().getCount() - countStep;
                        int countInThisStep = cur.getValue().getCount() - countBeyondThisStep;
                        countAccumulation += countInThisStep;
                        costAccumulation += cur.getKey() * countInThisStep;
                        countRangeMap.put(key, costAccumulation / countAccumulation);
                        countAccumulation = countBeyondThisStep;
                        costAccumulation = cur.getKey() * countBeyondThisStep;
                        break;
                    } else if (countAccumulation + cur.getValue().getCount() < countStep) {
                        countAccumulation += cur.getValue().getCount();
                        costAccumulation += cur.getKey() * cur.getValue().getCount();
                    }
                }
            }
        }

        request.setAttribute("mostCostLogs", AccessLogAnalyzer.mostCostLogs);
        request.setAttribute("costRangeMap", costRangeMap);
        request.setAttribute("totalCount", totalCount);
        request.setAttribute("countRangeMap", countRangeMap);
    }

    private String makeRangeKey(int[] range)
    {
        return range[0] + " - " + (range.length == 1 ? "" : range[1]);
    }

}
